﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace SharedGenomics.Core
{
    public class TextDataTableReader : IEnumerable<TextDataRow>
    {
        private KeyedIndexedCollection<string, string> _columnNames;

        public TextDataTableReader(string filePath)
            : this(filePath, ",")
        {
        }

        public TextDataTableReader(string filePath, string fieldSeparator)
            : this(new TextFileReader(filePath), fieldSeparator)
        {
        }

        public TextDataTableReader(Stream fileStream, string fieldSeparator)
            : this(new TextFileReader(fileStream), fieldSeparator)
        {
        }

        public TextDataTableReader(IEnumerable<string> lines, string fieldSeparator)
        {
            lines.ThrowIfNull("lines");

            this.LinesEnumerator = (lines ?? Enumerable.Empty<string>()).GetEnumerator();
            this.FieldSeparator = fieldSeparator;
            this._columnNames = new KeyedIndexedCollection<string, string>(s => s, StringComparer.CurrentCultureIgnoreCase, StringComparer.CurrentCultureIgnoreCase);

            this.LoadColumns();
        }

        public bool ColumnExists(string columnName)
        {
            return this.ColumnNameList.ContainsKey(columnName);
        }

        protected string[] GetLineElements(string line)
        {
            return line == null
                ? new string[] { }
                : line.Split(new[] { this.FieldSeparator }, StringSplitOptions.None).Select(e => e.Trim()).ToArray();
        }

        private void LoadColumns()
        {
            if (this.LinesEnumerator.MoveNext())
            {
                this._columnNames.AddRange(this.GetLineElements(this.LinesEnumerator.Current));
            }
        }

        public virtual IEnumerator<TextDataRow> GetEnumerator()
        {
            TextDataRow row = new TextDataRow(this.ColumnNameList);

            while(this.LinesEnumerator.MoveNext())
            {
                row.ColumnData = this.GetLineElements(this.LinesEnumerator.Current);
                yield return row;
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        private IEnumerator<string> LinesEnumerator { get; set; }
        private string FieldSeparator { get; set; }

        private KeyedIndexedCollection<string, string> ColumnNameList
        {
            get
            {
                return this._columnNames;
            }
        }

        public System.Collections.ObjectModel.ReadOnlyCollection<string> ColumnNames
        {
            get { return new System.Collections.ObjectModel.ReadOnlyCollection<string>(this.ColumnNameList); }
        }
    }
}
